#include "list.h"

//删除和拿回的操作也要用到find操作，所以把find函数拆开,并设置为静态函数，即只在内部使用
static node *find_(LIST *ptr, const void *key, list_cmp *cmp)
{
	node *current;
	for (current = ptr->head.next; current != &ptr->head; current = current->next)
	{
		if (cmp(key, current->data) == 0) //使用由用户书写的回调函数,==0表示找到
			break;
	}
	return current; //如果没找到则current = &ptr->head,而头结点的数据域正好为为空current->data = NULL;
}

LIST *list_create(int initsize)
{
	LIST *new = malloc(sizeof(LIST));
	printf("size of LIST = %ld\n", sizeof(LIST));
	printf("size of node = %ld\n", sizeof(new->head));
	if (new == NULL)
		return NULL;
	new->size = initsize;
	new->head.pre = &new->head;
	new->head.next = &new->head;
	return new;
}

//不知道用户的数据类型，用void *,且用户不希望你改他的数据，用const
//mode确定插入方式
int list_insert(LIST *ptr, const void *data, int mode)
{
	node *newnode = malloc(sizeof(node) + ptr->size);  //**关键**
	if (newnode == NULL)
		return -1;

	//不确定数据类型，使用memcpy函数拷贝过来
	memcpy(newnode->data, data, ptr->size);

	if (mode == LIST_FORWARD)
	{
		newnode->pre = &ptr->head;  //头部结点的前驱是头结点
		newnode->next = ptr->head.next;
	}
	else if (mode == LIST_BACKWARD)
	{
		newnode->pre = ptr->head.pre;   
		newnode->next = &ptr->head;    //尾部结点的后继是头结点
	}
	else
		return -3;

	//这两句是尾部插入和首部插入都要执行的
	newnode->pre->next = newnode;  //新结点的前驱的后继是自己
	newnode->next->pre = newnode;  //新结点的后继的前驱是自己

	return 0;
}

void list_show(LIST *ptr, list_op *op)
{
	node *current = ptr->head.next; //跳过没有数据的头结点
	while (current != &ptr->head)
	{
		op(current->data);
		current = current->next;
	}
}

int list_delete(LIST *ptr,const void * key,list_cmp * cmp)
{
	struct node_st * node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return -1;       //链表中没有要删除的
	node->pre->next = node->next;
	node->next->pre = node->pre;
	free(node);
	return 0;
}

int list_fetch(LIST *ptr,const void * key,list_cmp *cmp,void * data)
{
	struct node_st * node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return -1;
	node->pre->next = node->next;
	node->next->pre = node->pre;
	if(data != NULL)
		memcpy(data,node->data,ptr->size);  //把数据拷贝出来
	free(node);
	return 0;
}

void list_destory(LIST **ptr)
{
	node *current, *next;
	LIST *p = *ptr;
	for (current = p->head.next; current != &p->head; current = next)
	{
		next = current->next;
		free(current);
	}
	free(p);     //释放头结点
	*ptr = NULL; //如果不使用二级指针传参而使用一级指针，则这里置为NULL没有意义,仍然会产生野指针
}

void *list_find(LIST *ptr, void *key, list_cmp *cmp)
{
	node *p = find_(ptr, key, cmp);
	if (p == &ptr->head)
		return NULL; //人为给予空指针
	return p->data;
}
